import {
  ModuleFields,
  TextField,
  BooleanField,
  ColorField,
  NumberField,
  FieldGroup,
} from '@hubspot/cms-components/fields';

// ─── CSS ─────────────────────────────────────────────────────────────────────

const css = `
  .qli * { box-sizing: border-box; }
  .qli { font-family: system-ui, -apple-system, sans-serif; }

  .qli-card {
    background: #fff;
    border-radius: var(--qli-radius);
    padding: 28px 32px;
    box-shadow: 0 2px 16px rgba(0,0,0,0.06);
    margin-bottom: 16px;
  }

  .qli-header { margin-bottom: 20px; }
  .qli-heading    { font-size: 19px; font-weight: 900; color: #1e293b; margin: 0 0 4px; }
  .qli-subheading { font-size: 13px; color: #64748b; margin: 0; }

  /* Table wrapper — overflow for narrow viewports */
  .qli-wrap { overflow-x: auto; margin: 0 -4px; }

  .qli-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
  }

  /* Header row */
  .qli-table thead th {
    padding: 0 12px 10px;
    font-size: 11px; font-weight: 700; letter-spacing: 0.5px;
    text-transform: uppercase; color: #94a3b8;
    border-bottom: 2px solid #e2e8f0;
    white-space: nowrap;
  }
  .qli-th-product { text-align: left; }
  .qli-th-qty, .qli-th-price, .qli-th-disc, .qli-th-total { text-align: right; }

  /* Body rows */
  .qli-table tbody tr { border-bottom: 1px solid #f1f5f9; }
  .qli-table tbody tr:last-child { border-bottom: none; }

  .qli-table td {
    padding: 14px 12px;
    vertical-align: top;
  }
  .qli-td-product { text-align: left; }
  .qli-td-qty, .qli-td-price, .qli-td-disc, .qli-td-total {
    text-align: right; white-space: nowrap;
  }

  /* Product cell content */
  .qli-name { font-weight: 600; color: #1e293b; display: block; }
  .qli-sku {
    display: block; margin-top: 3px;
    font-size: 11px; font-family: monospace; letter-spacing: 0.3px; color: #94a3b8;
  }
  .qli-desc {
    display: block; margin-top: 5px;
    font-size: 12px; color: #64748b; line-height: 1.6;
  }
  .qli-desc p              { margin: 0 0 4px; }
  .qli-desc p:last-child   { margin: 0; }
  .qli-desc ul, .qli-desc ol { margin: 4px 0; padding-left: 16px; }
  .qli-desc li             { margin-bottom: 2px; }

  /* Recurring billing frequency badge */
  .qli-freq {
    display: inline-block; margin-top: 4px;
    font-size: 10px; font-weight: 700; letter-spacing: 0.3px;
    padding: 2px 7px; border-radius: 99px;
    color: var(--qli-primary); background: var(--qli-primary-faint);
  }

  /* Value cells */
  .qli-qty-val   { color: #475569; font-weight: 500; }
  .qli-price-val { color: #475569; }
  .qli-disc-val  { color: #16a34a; }
  .qli-disc-nil  { color: #e2e8f0; }
  .qli-total-val { font-weight: 600; color: #1e293b; }

  /* Empty state */
  .qli-empty {
    padding: 32px 12px; text-align: center;
    font-size: 13px; color: #94a3b8; font-style: italic;
  }

  /* Subtotal footer */
  .qli-foot td {
    padding: 14px 12px;
    border-top: 2px solid #e2e8f0;
  }
  .qli-foot-label {
    text-align: right !important;
    font-size: 11px; font-weight: 700; letter-spacing: 0.5px;
    text-transform: uppercase; color: #64748b;
  }
  .qli-foot-val {
    text-align: right !important;
    font-size: 16px; font-weight: 900; color: #1e293b; white-space: nowrap;
  }
`;

// ─── Helpers ─────────────────────────────────────────────────────────────────

function fmtCurrency(amount: number | null, currency: string, locale: string): string {
  if (amount == null) return '—';
  try {
    return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(amount);
  } catch {
    return `${currency} ${(amount ?? 0).toFixed(2)}`;
  }
}

const FREQ_LABELS: Record<string, string> = {
  monthly:        'Monthly',
  quarterly:      'Quarterly',
  semi_annually:  'Semi-annual',
  annually:       'Annual',
  per_week:       'Weekly',
  per_two_weeks:  'Bi-weekly',
};

function descriptionHtml(item: any): string {
  const rich  = item.hs_rich_text_description || '';
  const plain = item.description || '';
  // If rich text contains actual HTML tags, use it; otherwise convert plain text newlines
  return rich.includes('<') ? rich : plain.replace(/\n/g, '<br>');
}

function parsePrefixes(raw: string): string[] {
  return raw.split(',').map((s: string) => s.trim()).filter(Boolean);
}

// ─── Component ───────────────────────────────────────────────────────────────

export function Component({ fieldValues, hublData }: any) {
  const primary = fieldValues?.styles?.primary?.color || hublData?.brandPrimary || '#6366f1';
  const radius  = fieldValues?.styles?.radius         ?? 16;

  const heading        = fieldValues?.content?.heading    || 'Products & Services';
  const subheading     = fieldValues?.content?.subheading || '';
  const showSku        = String(fieldValues?.content?.showSku)        !== 'false';
  const showDesc       = String(fieldValues?.content?.showDesc)       !== 'false';
  const showUnitPrice  = String(fieldValues?.content?.showUnitPrice)  !== 'false';
  const showDiscount   = String(fieldValues?.content?.showDiscount)   !== 'false';
  const showSubtotal   = String(fieldValues?.content?.showSubtotal)   !== 'false';
  const registerAnchor = String(fieldValues?.content?.registerAnchor) !== 'false';

  const includePrefixes = parsePrefixes(fieldValues?.content?.includeSkuPrefixes || '');
  const excludePrefixes = parsePrefixes(fieldValues?.content?.excludeSkuPrefixes || '');

  const allItems: any[] = hublData?.lineItems || [];
  const currency = hublData?.currency || 'EUR';
  const locale   = hublData?.locale   || 'en';

  const primaryFaint = `${primary}18`;
  const fmt = (n: number | null) => fmtCurrency(n, currency, locale);

  // ── Filter ─────────────────────────────────────────────────────────────────
  const items = allItems.filter((item: any) => {
    const sku = item.hs_sku || '';
    // Include filter: item must match at least one prefix (items without SKU are excluded)
    if (includePrefixes.length > 0) {
      if (!sku || !includePrefixes.some((p: string) => sku.startsWith(p))) return false;
    }
    // Exclude filter: items with a matching SKU prefix are removed (no-SKU items pass through)
    if (excludePrefixes.length > 0) {
      if (sku && excludePrefixes.some((p: string) => sku.startsWith(p))) return false;
    }
    return true;
  });

  // ── Derived state ──────────────────────────────────────────────────────────
  const hasDiscounts = items.some((item: any) => (item.hs_total_discount || 0) > 0);
  const showDiscCol  = showDiscount && hasDiscounts;
  const subtotal     = items.reduce((sum: number, item: any) => sum + (item.amount || 0), 0);

  // Columns to the left of Total — used for colspan in subtotal row
  const leftCols = 2 + (showUnitPrice ? 1 : 0) + (showDiscCol ? 1 : 0); // product + qty + …

  return (
    <>
      <style dangerouslySetInnerHTML={{ __html: css }} />
      <div
        id={registerAnchor ? 'qs-products' : undefined}
        className="qli"
        style={{
          maxWidth: 800,
          margin: '0 auto',
          padding: '0 0 8px',
          ['--qli-primary' as any]:       primary,
          ['--qli-radius' as any]:        `${radius}px`,
          ['--qli-primary-faint' as any]: primaryFaint,
        }}
      >
        <div className="qli-card">

          {/* Header */}
          <div className="qli-header">
            {heading    && <h2 className="qli-heading">{heading}</h2>}
            {subheading && <p className="qli-subheading">{subheading}</p>}
          </div>

          <div className="qli-wrap">
            <table className="qli-table">
              <thead>
                <tr>
                  <th className="qli-th-product">Product</th>
                  <th className="qli-th-qty">Qty</th>
                  {showUnitPrice && <th className="qli-th-price">Unit price</th>}
                  {showDiscCol   && <th className="qli-th-disc">Discount</th>}
                  <th className="qli-th-total">Total</th>
                </tr>
              </thead>

              <tbody>
                {items.length === 0 ? (
                  <tr>
                    <td
                      className="qli-empty"
                      colSpan={2 + (showUnitPrice ? 1 : 0) + (showDiscCol ? 1 : 0) + 1}
                    >
                      No items to display
                    </td>
                  </tr>
                ) : items.map((item: any, i: number) => {
                  const freq     = item.recurringbillingfrequency;
                  const freqLabel = freq ? (FREQ_LABELS[freq] || freq) : null;
                  const discount  = item.hs_total_discount || 0;
                  const desc      = descriptionHtml(item);

                  return (
                    <tr key={item.id || i}>
                      <td className="qli-td-product">
                        <span className="qli-name">{item.name}</span>
                        {showSku && item.hs_sku && (
                          <span className="qli-sku">{item.hs_sku}</span>
                        )}
                        {showDesc && desc && (
                          <span
                            className="qli-desc"
                            dangerouslySetInnerHTML={{ __html: desc }}
                          />
                        )}
                      </td>

                      <td className="qli-td-qty">
                        <span className="qli-qty-val">{item.quantity}</span>
                      </td>

                      {showUnitPrice && (
                        <td className="qli-td-price">
                          <span className="qli-price-val">{fmt(item.price)}</span>
                          {freqLabel && (
                            <span className="qli-freq">{freqLabel}</span>
                          )}
                        </td>
                      )}

                      {showDiscCol && (
                        <td className="qli-td-disc">
                          {discount > 0
                            ? <span className="qli-disc-val">−{fmt(discount)}</span>
                            : <span className="qli-disc-nil">—</span>
                          }
                        </td>
                      )}

                      <td className="qli-td-total">
                        <span className="qli-total-val">{fmt(item.amount)}</span>
                      </td>
                    </tr>
                  );
                })}
              </tbody>

              {showSubtotal && items.length > 0 && (
                <tfoot>
                  <tr className="qli-foot">
                    <td colSpan={leftCols} className="qli-foot-label">Subtotal</td>
                    <td className="qli-foot-val">{fmt(subtotal)}</td>
                  </tr>
                </tfoot>
              )}
            </table>
          </div>

        </div>
      </div>
    </>
  );
}

// ─── Fields ──────────────────────────────────────────────────────────────────

export const fields = (
  <ModuleFields>
    <FieldGroup name="content" label="Content">
      <TextField    name="heading"    label="Section heading"    default="Products & Services" />
      <TextField    name="subheading" label="Section subheading" default="" />
      <BooleanField name="showSku"        label="Show SKU"              default={true} />
      <BooleanField name="showDesc"       label="Show description"      default={true} />
      <BooleanField name="showUnitPrice"  label="Show unit price column" default={true} />
      <BooleanField name="showDiscount"   label="Show discount column"   default={true} helpText="Column only appears when at least one line item has a discount" />
      <BooleanField name="showSubtotal"   label="Show subtotal row"      default={true} />
      <BooleanField
        name="registerAnchor"
        label="Register as Products nav anchor"
        default={true}
        helpText="Adds id='qs-products' so QuoteNav can link to this table. Disable on additional line-item tables — only one should be the anchor."
      />
      <TextField
        name="includeSkuPrefixes"
        label="Include only — SKU starts with"
        default=""
        helpText="Comma-separated prefixes. Only items whose SKU starts with one of these are shown. Items with no SKU are excluded. Leave blank to show all."
      />
      <TextField
        name="excludeSkuPrefixes"
        label="Exclude — SKU starts with"
        default=""
        helpText="Comma-separated prefixes. Items whose SKU starts with one of these are hidden. Items with no SKU are always shown. Leave blank to exclude nothing."
      />
    </FieldGroup>
    <FieldGroup name="styles" label="Styles" tab="STYLE">
      <ColorField  name="primary" label="Accent colour"     default={{ color: '', opacity: 100 }} helpText="Leave blank to use brand colour" />
      <NumberField name="radius"  label="Border radius (px)" default={16} />
    </FieldGroup>
  </ModuleFields>
);

// ─── Meta ─────────────────────────────────────────────────────────────────────

export const meta = {
  label: 'Quote Line Items',
  content_types: ['QUOTE', 'QUOTE_BLUEPRINT'],
};

// ─── hublDataTemplate ────────────────────────────────────────────────────────

export const hublDataTemplate = `
  {% set sortedItems = quoteTemplateContext.lineItems|sort(attribute="hs_position_on_quote") %}

  {% set hublData = {
    "lineItems": sortedItems,
    "currency":  quoteTemplateContext.quote.hs_currency,
    "locale":    quoteTemplateContext.quote.hs_locale,
    "isPdf":     true if quoteTemplateContext.quote.hs_pdf_generation_status == "PDF_GENERATING" else false,
    "brandPrimary": brand_settings.primaryColor.hex
  } %}
`;
